<script setup lang="ts">
import { inject, onMounted, onUnmounted, reactive, ref, watch } from 'vue';

import { ElCheck, ElDelete, ElPlus } from '@vben/icons';

import {
  ElAlert,
  ElButton,
  ElCheckbox,
  ElCol,
  ElCollapse,
  ElCollapseItem,
  ElIcon,
  ElInput,
  ElMessage,
  ElOption,
  ElPopover,
  ElRadio,
  ElRadioGroup,
  ElRow,
  ElSelect,
  ElSlider,
  ElTable,
  ElTableColumn,
} from 'element-plus';

import { vectorServiceApi } from '#/api';
import { usePublicStore } from '#/store';

const emits = defineEmits(['confirmBtnAvalible']);
const publicStore = usePublicStore();
const currentLayer = inject('currentSelectedLayer') as any;
const activeNames = ref(['ClusterRules']);
// const gradualValueRender = new GradualValueRender()
// const basedRule = ref('global')
const singleColor = ref('#ff0000');
const opacity = ref(100);
const size = ref(10);
const blur = ref(0);
const keepingLayer = ref(true);

const isCircleOpenOutline = ref('closed');
const clusterOptions = reactive({
  layer: currentLayer.value,
  point_count: 0,
  keepingLayer:
    currentLayer.value.renderType[1] === 'cluster' ? false : keepingLayer,
  clusterRadius: 50,
  clusterMaxZoom: 18,
  clusterRules: [
    // {
    //   label: '规则1',
    //   value: 'rule1',
    //   rule: {
    //     step: 0,
    //     color: '#51bbd6',
    //     radius: 20
    //   }
    // },
    // {
    //   label: '规则2',
    //   value: 'rule2',
    //   rule: {
    //     step: 60,
    //     color: '#f1f075',
    //     radius: 30
    //   }
    // },
    // {
    //   label: '规则3',
    //   value: 'rule3',
    //   rule: {
    //     step: 450,
    //     color: '#f28cb1',
    //     radius: 40
    //   }
    // }
  ] as any,
  isSymbolText: true,
  symbolText: {
    layout: {
      visibility: 'visible',
      'text-field': ['get', 'point_count_abbreviated'],
      'text-font': ['Open Sans Semibold'],
      'text-size': 12,
    },
    paint: {
      'text-color': '#938080',
    },
  },
  mapLayer: {} as any,
  symbolLayer: {} as any,
  // noneClusterLayer: {} as any,
  noneClusterLayerOptions: {
    id: `${currentLayer.value.id}_noneCluster`,
    type: 'circle',
    source: currentLayer.value.source,
    filter: ['!', ['has', 'point_count']],
    layout: {
      visibility: 'visible',
    },
    paint: {
      'circle-opacity': opacity,
      'circle-blur': blur,
      'circle-color': singleColor,
      'circle-radius': size,
      'circle-stroke-width': 3,
      'circle-stroke-color': '#ffff00',
      'circle-stroke-opacity': 100,
    },
  },
  isCircleOpenOutline,
});

const fonts = ref<Array<string>>([
  'Open Sans Semibold',
  'Open Sans Light',
  'Open Sans Bold',
  'Open Sans Extra Bold',
  'Roboto Thin',
  'Roboto Light',
  'Roboto Regular',
  'Roboto Medium',
  'Roboto Bold',
  'Roboto Black',
  '宋体',
]);
const circleBlur = ref(
  `blur(${clusterOptions.noneClusterLayerOptions.paint['circle-blur']}px)`,
);

const renderParamsReturn = () => {
  const renderParams = currentLayer.value.renderParams;
  clusterOptions.clusterMaxZoom = renderParams.clusterMaxZoom;
  clusterOptions.clusterRadius = renderParams.clusterRadius;
  keepingLayer.value = renderParams.keepingLayer;
  clusterOptions.isSymbolText = renderParams.isSymbolText;
  clusterOptions.symbolText = renderParams.symbolText;
  clusterOptions.clusterRules = renderParams.clusterRules;

  if (renderParams.isCircleOpenOutline === 'open') {
    clusterOptions.noneClusterLayerOptions.paint['circle-stroke-color'] =
      renderParams.noneClusterLayerOptions_paint['circle-stroke-color'];
    clusterOptions.noneClusterLayerOptions.paint['circle-stroke-width'] =
      renderParams.noneClusterLayerOptions_paint['circle-stroke-width'];
    clusterOptions.noneClusterLayerOptions.paint['circle-stroke-opacity'] =
      renderParams.noneClusterLayerOptions_paint['circle-stroke-opacity'];
  }
  clusterOptions.isCircleOpenOutline = renderParams.isCircleOpenOutline;
  blur.value = renderParams.noneClusterLayerOptions_paint['circle-blur'];
  size.value = renderParams.noneClusterLayerOptions_paint['circle-radius'];
  singleColor.value =
    renderParams.noneClusterLayerOptions_paint['circle-color'];
  opacity.value = renderParams.noneClusterLayerOptions_paint['circle-opacity'];
};
// 请求当前图层字段值
const requestFeatureCount = async () => {
  clusterOptions.point_count =
    await vectorServiceApi.getFeatureCountFromGeojson(
      currentLayer.value.source.replace('_cluster', ''),
    );
};
const addClusterRule = () => {
  if (
    clusterOptions.clusterRules.length > 0 &&
    (clusterOptions.clusterRules[clusterOptions.clusterRules.length - 1]
      .step === '' ||
      clusterOptions.clusterRules[clusterOptions.clusterRules.length - 1]
        .radius === '')
  ) {
    ElMessage({
      message: '规则不能为空',
      type: 'warning',
    });
    return;
  }
  clusterOptions.clusterRules.push({
    label: `规则${clusterOptions.clusterRules.length + 1}`,
    value: `rule${clusterOptions.clusterRules.length + 1}`, // 根据表头的列名添加对应的属性
    step: clusterOptions.clusterRules.length === 0 ? 0 : '',
    color: '#ff0000',
    radius: '',
    disabled:
      clusterOptions.clusterRules.length === 0 ? 'disabled' : 'available',
  });
  // console.log(clusterRules.value);
};

const deleteClusterRule = (index: number) => {
  clusterOptions.clusterRules.splice(index, 1);
  // 更新剩余规则的名称
  for (let i = index; i < clusterOptions.clusterRules.length; i++) {
    clusterOptions.clusterRules[i].label = `规则${i + 1}`;
    clusterOptions.clusterRules[i].value = `rule${i + 1}`;
  }
};

const confirmRules = () => {
  if (clusterOptions.clusterRules.length === 0) {
    ElMessage({
      message: '规则不能为空',
      type: 'warning',
    });
    return;
  }
  // 检查最后一个规则是否有元素为空
  const isEmptyClusterRules = Object.values(
    clusterOptions.clusterRules[clusterOptions.clusterRules.length - 1],
  ).includes('');
  if (isEmptyClusterRules) {
    ElMessage({
      message: '规则不能为空',
      type: 'warning',
    });
    return;
  }
  const overFeatureCount = clusterOptions.clusterRules.some(
    (item: { step: number }) => item.step > clusterOptions.point_count,
  );
  if (overFeatureCount) {
    ElMessage({
      message: '分隔点数值不得超过要素个数',
      type: 'warning',
    });
    return;
  }
  emits('confirmBtnAvalible', true);
  ElMessage.success('规则确认通过！');

  // Promise.all([new Promise((resolve, reject) => {
  //   serviceDataVSceneApi.getSceneLayer(currentLayer.value.id, "geojson", "cluster").then(res => {
  //     if (res.code === 200) {
  //       console.log(res.data)
  //       resolve(res.data)
  //     } else {
  //       reject(res.msg)
  //     }
  //   })
  // }), new Promise((resolve, reject) => {
  //   serviceDataVSceneApi.getSceneLayer(currentLayer.value.id, "geojson", "symbol").then(res => {
  //     if (res.code === 200) {
  //       console.log(res.data)
  //       resolve(res.data)
  //     } else {
  //       reject(res.msg)
  //     }
  //   })
  // }), new Promise((resolve, reject) => {
  //   serviceDataVSceneApi.getSceneLayer(currentLayer.value.id, "geojson", "circle").then(res => {
  //     if (res.code === 200) {
  //       console.log(res.data)
  //       resolve(res.data)
  //     } else {
  //       reject(res.msg)
  //     }
  //   })
  // })]).then((layers: any) => {
  //   console.log(layers)
  //   clusterOptions.mapLayer = layers[0]
  //   clusterOptions.symbolLayer = layers[1]
  //   clusterOptions.noneClusterLayer = layers[2]
  //   emits('confirmBtnAvalible', true)
  //   ElMessage.success('规则确认通过！')
  //   console.log(clusterOptions)
  // })
};
const changeBlur = () => {
  circleBlur.value = `blur(${clusterOptions.noneClusterLayerOptions.paint['circle-blur']}px)`;
};
const drawCircle = () => {
  // console.log(singleValueRenderParams)
  const canvas = document.querySelector('#graph-preview') as any;
  const ctx = canvas.getContext('2d') as any;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  const radius = size.value;
  const color = singleColor.value;
  const circleOpacity = opacity.value;
  // console.log(radius, color)

  // const { outline, outlineColor, outlineOpacity, outlineWidth } = singleValueRenderParams.value.style.point
  const {
    'circle-stroke-color': outlineColor,
    'circle-stroke-opacity': outlineOpacity,
    'circle-stroke-width': outlineWidth,
  } = clusterOptions.noneClusterLayerOptions.paint;
  const centerX = canvas.width / 2;
  const centerY = canvas.height / 2;
  // 判断轮廓线是否开启
  if (isCircleOpenOutline.value === 'open') {
    ctx.globalAlpha = outlineOpacity / 100;
    ctx.beginPath();
    // console.log(radius + outlineWidth / 2)
    ctx.arc(centerX, centerY, radius + outlineWidth / 2, 0, 2 * Math.PI);
    ctx.lineWidth = outlineWidth; // 轮廓线宽度
    ctx.strokeStyle = outlineColor; // 轮廓线颜色
    ctx.stroke();
    ctx.closePath();
  }
  ctx.globalAlpha = circleOpacity / 100;
  ctx.beginPath();
  ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
  ctx.fillStyle = color;
  ctx.fill();
  ctx.closePath();
};
const drawEntry = () => {
  drawCircle();
};

watch(
  clusterOptions,
  () => {
    publicStore.setRenderOptions(clusterOptions);
  },
  {
    deep: true,
  },
);
onMounted(() => {
  if (currentLayer.value.renderType[1] === 'cluster') {
    renderParamsReturn();
  }
  emits('confirmBtnAvalible', false);
  requestFeatureCount(); // 请求要素个数
  changeBlur();
  drawCircle();
});
onUnmounted(() => {
  emits('confirmBtnAvalible', true);
});
</script>

<template>
  <div class="all">
    <ElRow class="itemRow">
      <ElCol :span="4">
        <span class="label-style"> 聚合半径： </span>
      </ElCol>
      <ElCol :span="20">
        <ElInput
          v-model.number="clusterOptions.clusterRadius"
          placeholder="Please input"
          size="small"
        >
          <template #append>像素</template>
        </ElInput>
      </ElCol>
    </ElRow>
    <ElRow class="itemRow">
      <ElCol :span="6">
        <span class="label-style"> 最大缩放级别： </span>
      </ElCol>
      <ElCol :span="18">
        <ElSlider
          v-model.number="clusterOptions.clusterMaxZoom"
          :min="1"
          :max="20"
          show-input
          size="small"
        />
      </ElCol>
    </ElRow>
    <ElAlert
      :title="`当前数据要素个数为：${clusterOptions.point_count}，分隔点数值不得超过${clusterOptions.point_count}`"
      :closable="false"
      type="info"
      show-icon
      center
      style="height: 25px"
    />
    <ElCollapse v-model="activeNames" accordion>
      <ElCollapseItem title="聚合规则" name="ClusterRules">
        <ElRow class="itemRow">
          <ElCol :span="4">
            <ElButton
              type="primary"
              size="small"
              :icon="ElPlus"
              @click="addClusterRule"
              style="height: 30px; padding: 5px; margin-top: 59px"
            >
              添加规则
            </ElButton>
          </ElCol>
          <ElCol :span="20" style="height: 160px">
            <div
              v-if="clusterOptions.clusterRules.length === 0"
              style="
                width: 100%;
                height: 150px;
                line-height: 150px;
                color: rgb(127 127 127 / 50%);
                text-align: center;
              "
            >
              No Cluster Rules
            </div>
            <ElTable
              :data="clusterOptions.clusterRules"
              style="width: 100%"
              max-height="170"
              v-show="clusterOptions.clusterRules.length > 0"
              size="small"
            >
              <ElTableColumn label="名称" width="100">
                <template #default="scope">
                  <ElInput
                    v-model="scope.row.label"
                    :disabled="true"
                    size="small"
                  />
                </template>
              </ElTableColumn>
              <ElTableColumn label="分隔点" width="80">
                <template #default="scope">
                  <ElInput
                    v-model.number="scope.row.step"
                    :disabled="scope.row.disabled === 'disabled' ? true : false"
                    size="small"
                  />
                </template>
              </ElTableColumn>
              <ElTableColumn label="颜色" width="100">
                <template #default="scope">
                  <ElInput
                    v-model="scope.row.color"
                    class="colorInput"
                    type="color"
                    size="small"
                  />
                </template>
              </ElTableColumn>
              <ElTableColumn label="半径" width="80">
                <template #default="scope">
                  <ElInput v-model.number="scope.row.radius" size="small" />
                </template>
              </ElTableColumn>
              <ElTableColumn>
                <template #default="scope">
                  <ElButton
                    type="danger"
                    size="small"
                    @click.prevent="deleteClusterRule(scope.$index)"
                    :icon="ElDelete"
                    style="margin-right: 5px"
                  />
                </template>
              </ElTableColumn>
            </ElTable>
          </ElCol>
        </ElRow>
      </ElCollapseItem>
      <ElCollapseItem title="聚合标签" name="clusterTag">
        <ElRow class="itemRow">
          <ElCol :span="8">
            <span class="label-style"> 是否添加聚合标签： </span>
          </ElCol>
          <ElCol :span="16">
            <div>
              <ElRadioGroup v-model="clusterOptions.isSymbolText" size="small">
                <ElRadio :label="true">开启</ElRadio>
                <ElRadio :label="false">关闭</ElRadio>
              </ElRadioGroup>
            </div>
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="4">
            <span class="label-style"> 字体： </span>
          </ElCol>
          <ElCol :span="20">
            <ElSelect
              size="small"
              v-model="clusterOptions.symbolText.layout['text-font'][0]"
              placeholder="请选择字体"
              style="width: 100%"
              :disabled="!clusterOptions.isSymbolText"
            >
              <ElOption
                v-for="font in fonts"
                :key="font"
                :label="font"
                :value="font"
              />
            </ElSelect>
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="4">
            <span class="label-style"> 字体大小： </span>
          </ElCol>
          <ElCol :span="20">
            <ElInput
              v-model.number="clusterOptions.symbolText.layout['text-size']"
              placeholder="Please input"
              :disabled="!clusterOptions.isSymbolText"
              size="small"
            >
              <template #append>像素</template>
            </ElInput>
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="4">
            <span class="label-style"> 字体颜色： </span>
          </ElCol>
          <ElCol :span="20">
            <ElInput
              class="colorInput"
              v-model="clusterOptions.symbolText.paint['text-color']"
              type="color"
              :disabled="!clusterOptions.isSymbolText"
              size="small"
            />
          </ElCol>
        </ElRow>
      </ElCollapseItem>
      <ElCollapseItem title="非聚合点样式" name="noneCluster">
        <ElRow class="itemRow">
          <ElCol :span="4">
            <span class="label-style"> 预览： </span>
          </ElCol>
          <ElCol :span="20">
            <div id="canvas-container">
              <canvas id="graph-preview" width="380" height="100"></canvas>
            </div>
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="4">
            <span class="label-style"> 颜色： </span>
          </ElCol>
          <ElCol :span="20">
            <ElInput
              @input="drawEntry"
              class="colorInput"
              v-model="singleColor"
              type="color"
              size="small"
            />
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="6">
            <span class="label-style"> 不透明度： </span>
          </ElCol>
          <ElCol :span="18">
            <ElSlider
              @input="drawEntry"
              v-model.number="opacity"
              show-input
              size="small"
            />
          </ElCol>
        </ElRow>
        <ElRow v-if="currentLayer.dataType !== 'MULTIPOLYGON'" class="itemRow">
          <ElCol :span="4">
            <span class="label-style">
              {{ currentLayer.dataType === 'POINT' ? '大小' : '宽度' }}
            </span>
          </ElCol>
          <ElCol :span="20">
            <ElInput
              @input="drawEntry"
              v-model.number="size"
              placeholder="Please input"
              size="small"
            >
              <template #append>像素</template>
            </ElInput>
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="4">
            <span class="label-style"> 模糊度： </span>
          </ElCol>
          <ElCol :span="20">
            <ElSlider
              @input="changeBlur"
              v-model.number="blur"
              show-input
              size="small"
            />
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="8">
            <span class="label-style"> 是否开启外轮廓线： </span>
          </ElCol>
          <ElCol :span="16">
            <div>
              <ElRadioGroup
                v-model="isCircleOpenOutline"
                @change="drawEntry"
                size="small"
              >
                <ElRadio label="open">开启</ElRadio>
                <ElRadio label="closed">关闭</ElRadio>
              </ElRadioGroup>
            </div>
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="6">
            <span class="label-style"> 外轮廓线颜色： </span>
          </ElCol>
          <ElCol :span="18">
            <ElInput
              @input="drawEntry"
              class="colorInput"
              v-model="
                clusterOptions.noneClusterLayerOptions.paint[
                  'circle-stroke-color'
                ]
              "
              type="color"
              :disabled="isCircleOpenOutline === 'closed'"
              size="small"
            />
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="6">
            <span class="label-style"> 外轮廓线线宽： </span>
          </ElCol>
          <ElCol :span="18">
            <ElInput
              @input="drawEntry"
              v-model.number="
                clusterOptions.noneClusterLayerOptions.paint[
                  'circle-stroke-width'
                ]
              "
              placeholder="Please input"
              :disabled="isCircleOpenOutline === 'closed'"
              size="small"
            >
              <template #append>像素</template>
            </ElInput>
          </ElCol>
        </ElRow>
        <ElRow class="itemRow">
          <ElCol :span="8">
            <span class="label-style"> 外轮廓线不透明度： </span>
          </ElCol>
          <ElCol :span="16">
            <ElSlider
              @input="drawEntry"
              v-model.number="
                clusterOptions.noneClusterLayerOptions.paint[
                  'circle-stroke-opacity'
                ]
              "
              :disabled="isCircleOpenOutline === 'closed'"
              show-input
              size="small"
            />
          </ElCol>
        </ElRow>
      </ElCollapseItem>
    </ElCollapse>

    <div class="keep-layer" v-if="currentLayer.renderType[1] !== 'cluster'">
      <ElCheckbox
        v-model="keepingLayer"
        label="保留原图层"
        size="large"
      />&nbsp;
      <ElPopover :width="170" placement="bottom">
        <template #reference>
          <ElIcon size="14" style="cursor: pointer">
            <InfoFilled />
          </ElIcon>
        </template>
        <template #default>
          <div style="display: flex; flex-direction: column; gap: 16px">
            <div>
              <p style="margin: 0; font-size: 13px">取消该选项将覆盖原图层</p>
            </div>
          </div>
        </template>
      </ElPopover>
      &nbsp;<ElAlert
        title="将生成新的图层，新图层将不再支持聚合图渲染以外的渲染方式"
        :closable="false"
        type="info"
        center
        style="height: 30px"
      />
    </div>

    <div
      style="
        display: flex;
        align-items: center;
        justify-content: center;
        height: 50px;
      "
    >
      <ElButton
        type="primary"
        size="small"
        :icon="ElCheck"
        @click="confirmRules"
        style="height: 30px"
      >
        确认规则
      </ElButton>
    </div>
  </div>
</template>

<style scoped>
.all {
  width: 100%;
}

.itemRow {
  width: 100%;
  padding: 5px;
}

.el-input {
  width: 100%;
}

.label-style {
  font-size: 15px;
}

.colorInput {
  caret-color: transparent;
}

:deep(.colorInput .el-input__inner:hover) {
  cursor: pointer;
}

:deep(.el-table .el-table__cell) {
  text-align: center;
}

.legend {
  margin-top: 2px;
}

:deep(.el-table:not(.el-table--border) .el-table__cell) {
  border: none;

  /* 去除表格边框 */
}

:deep(.el-table--small .cell) {
  height: 25px;
}

#graph-preview {
  position: absolute;
  top: 0;
  left: 0;
}

:deep(.el-collapse-item__header) {
  font-size: 15px;
  font-weight: 600;
}

#canvas-container {
  position: relative;
  width: 380px;
  height: 100px;
  /* stylelint-disable-next-line value-keyword-case */
  filter: v-bind(circleBlur);

  /* 设置模糊效果 */
}

.keep-layer {
  display: flex;
  align-items: center;
  justify-content: left;
}

:deep(.el-alert__title) {
  font-size: 13px;
}
</style>
